#include "bitmap.h"
#include "stdint.h"
#include "string.h"
#include "print.h"
#include "interrupt.h"
#include "debug.h"

/*将位图的每一个字节用0填充*/
void bitmat_init(struct bitmap* btmp){
	memset(btmp->bits, 0, btmp->btmp_bytes_len);
}

/*判断bit_idx位是否为1,，若为1，则返回true，否则返回false*/
bool bitmap_scan_test(struct bitmap* btmp, uint32_t bit_idx){
	uint32_t byte_idx = bit_idx / 8;
	uint32_t bit_odd = bit_idx % 8;
	return (btmp -> bits[byte_idx] & (BITMAP << bit_odd));
}

/*在位图中申请连续cnt个位，成功则返回其起始位下标，失败则返回-1*/
int bitmap_scan(struct bitmap* btmp, uint32_t cnt){
	//如果字节已无空闲位就下一个字节，先找到第一个有空闲位的字节
	uint32_t idx_byte = 0;
	while((0xff == btmp->bits[idx_byte])&&(idx_byte < btmp->btmp_bytes_len)){
		idx_byte++;
	}
	if(idx_byte == btmp->btmp_bytes_len){
		return -1;
	}
	//找到第一个空闲字节里的第一个空闲位
	int idx_bit = 0;
	while((uint8_t)(BITMAP_MASK << idx_bit) & btmp->bits[idx_byte]){
		idx_bit++;
	}
	int bit_idx_start == idx_byte * 8 + idx_bit;
	//如果只申请1位，现在就可以返回了
	if(cnt == 1){
		return bit_idx_start;
	}
	//btmp中剩余的位数
	uint32_t bit_left = (btmp->btmp_bytes_len * 8 - bit_idx_start);
	uint32_t next_bit = bit_idx_start + 1;
	uint32_t count = 1;
	
	bit_idx_start = -1;  //先将其置为-1，若找不到连续的位就直接返回
	while(bit_left-- > 0){
		if(!(bitmap_scan_test(btmp, next_bit))){    //next_bit为0,未占用
			count++;
		}else{
			count = 0;          //next_bit为1，count归0重新开始计算
		}
		if(count == cnt){
			bit_idx_start = next_bit - cnt + 1;
			break;
		}
		next_bit++;
	}
	return bit_idx_start;
}

void bitmap_set(struct bitmap* btmp, uint32_t bit_idx, int8_t value){
	ASSERT((value == 0) || (value == 1));
	uint32_t byte_idx = bit_idx / 8;
	uint32_t bit_odd = bit_idx % 8;
	if(value) {
		btmp -> bits[byte_idx] |= (BITMAP_MASK << bit_odd);
	}else{
		btmp -> bits[byte_idx] &= (BITMAP_MASK << bit_odd);
	}
}